<template>
  <div class="ansible-audit-container">
    <!-- 星空背景 -->
    <div class="starry-background">
      <div class="stars"></div>
      <div class="stars2"></div>
      <div class="stars3"></div>
    </div>

    <!-- 主要内容区域 -->
    <div class="audit-content">
      <!-- 页面标题 -->
      <div class="page-header glass-effect">
        <div class="header-content">
          <div class="title-section">
            <h1 class="page-title">
              <i class="fa fa-ship"></i>
              Harbor镜像管理
            </h1>
            <p class="page-subtitle">管理Harbor仓库中的镜像，包括查看、拉取、删除等操作</p>
          </div>
          <div class="stats-section">
            <div class="stat-card glass-effect">
              <div class="stat-number">{{ statistics?.total_images || 0 }}</div>
              <div class="stat-label">镜像总数</div>
            </div>
            <div class="stat-card glass-effect">
              <div class="stat-number">{{ statistics?.total_size || '0 MB' }}</div>
              <div class="stat-label">总大小</div>
            </div>
            <div class="stat-card glass-effect">
              <div class="stat-number">{{ statistics?.total_repositories || 0 }}</div>
              <div class="stat-label">仓库数量</div>
            </div>
          </div>
        </div>
      </div>

      <!-- 操作按钮 -->
      <div class="search-filters glass-effect">
        <el-form inline class="search-form">
          <div class="form-left">
            <el-select v-model="selectedRegistry" placeholder="选择Harbor仓库" class="server-select">
              <el-option
                v-for="registry in harborRegistries"
                :key="registry.id"
                :label="registry.name"
                :value="registry.id"
              >
                <div class="registry-option">
                  <i class="fa fa-ship"></i>
                  <span>{{ registry.name }}</span>
                  <span class="registry-url">({{ registry.url }})</span>
                </div>
              </el-option>
            </el-select>
            <el-select v-model="selectedProject" placeholder="选择项目" class="server-select" v-if="selectedRegistry">
              <el-option
                v-for="project in projects"
                :key="project.name"
                :label="project.name"
                :value="project.name"
              />
            </el-select>
          </div>
          <div class="form-right">
            <el-button type="primary" @click="refreshImages" class="glass-button refresh-button" :loading="loading">
              <i class="fa fa-refresh"></i>
              刷新镜像
            </el-button>
            <el-button @click="pullImage" class="glass-button add-button">
              <i class="fa fa-download"></i>
              拉取镜像
            </el-button>
            <el-button @click="cleanupImages" class="glass-button delete-button">
              <i class="fa fa-trash"></i>
              清理镜像
            </el-button>
          </div>
        </el-form>
      </div>

      <!-- 镜像列表 -->
      <div class="audit-table-section glass-effect">
        <div class="section-title">
          <i class="fa fa-ship"></i>
          Harbor镜像列表
        </div>

        <el-table
          :data="images"
          style="width: 100%"
          v-loading="loading"
          row-class-name="audit-row"
          class="audit-table"
        >
          <el-table-column prop="name" label="镜像名称" min-width="200" show-overflow-tooltip>
            <template #default="scope">
              <div class="config-name">
                <i class="fa fa-layer-group"></i>
                {{ scope.row.name }}
              </div>
            </template>
          </el-table-column>

          <el-table-column prop="tag" label="标签" min-width="80" show-overflow-tooltip />

          <el-table-column prop="digest" label="摘要" min-width="120" show-overflow-tooltip>
            <template #default="scope">
              <span class="image-id">
                {{ scope.row.digest ? scope.row.digest.substring(0, 12) : '' }}
              </span>
            </template>
          </el-table-column>

          <el-table-column prop="size" label="大小" min-width="80" show-overflow-tooltip>
            <template #default="scope">
              <span class="size-text">
                {{ scope.row.size }}
              </span>
            </template>
          </el-table-column>

          <el-table-column prop="push_time" label="推送时间" min-width="140" show-overflow-tooltip>
            <template #default="scope">
              <span class="time-text">
                {{ scope.row.push_time }}
              </span>
            </template>
          </el-table-column>

          <el-table-column label="操作" min-width="240" :show-overflow-tooltip="false">
            <template #default="scope">
              <div class="action-buttons">

                <el-button
                  @click="viewDetails(scope.row)"
                  size="small"
                  class="glass-button info-button"
                >
                  <i class="fa fa-info-circle"></i>
                  详情
                </el-button>
                <el-button
                  @click="startVulnerabilityScan(scope.row)"
                  size="small"
                  class="glass-button warning-button"
                >
                  <i class="fa fa-shield"></i>
                  漏洞扫描
                </el-button>
                <el-button
                  @click="deleteImage(scope.row)"
                  size="small"
                  class="glass-button delete-button"
                >
                  <i class="fa fa-trash"></i>
                  删除
                </el-button>
              </div>
            </template>
          </el-table-column>
        </el-table>

        <!-- 空状态 -->
        <div v-if="!loading && images.length === 0" class="empty-state">
          <div class="empty-content">
            <i class="fa fa-ship empty-icon"></i>
            <h3>暂无Harbor镜像</h3>
            <p>请选择Harbor仓库和项目后刷新数据</p>
          </div>
        </div>
      </div>
    </div>

    <!-- 拉取镜像对话框 -->
    <el-dialog
      v-model="pullDialogVisible"
      title="拉取镜像到本地Docker"
      width="600px"
      class="glass-dialog"
    >
      <div class="pull-dialog-content">
        <div class="dialog-section">
          <h4>选择要拉取的镜像</h4>
          <el-select v-model="selectedImage" placeholder="选择镜像" class="full-width">
            <el-option
              v-for="image in images"
              :key="`${image.name}:${image.tag}`"
              :label="`${image.name}:${image.tag}`"
              :value="`${image.name}:${image.tag}`"
            >
              <div class="image-option">
                <span class="image-name">{{ image.name }}:{{ image.tag }}</span>
                <span class="image-size">{{ image.size }}</span>
              </div>
            </el-option>
          </el-select>
        </div>

        <div class="dialog-section" v-if="selectedImage">
          <h4>拉取命令</h4>
          <div class="command-box">
            <code>docker pull {{ getRegistryUrl() }}/{{ selectedImage }}</code>
          </div>
          <p class="command-tip">
            <i class="fa fa-info-circle"></i>
            点击确定将复制命令到剪贴板，请在Docker环境中执行
          </p>
        </div>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="pullDialogVisible = false" class="glass-button">
            取消
          </el-button>
          <el-button @click="confirmPullImage" type="primary" class="glass-button primary-button">
            <i class="fa fa-copy"></i>
            复制命令
          </el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 镜像详情对话框 -->
    <el-dialog
      v-model="detailsDialogVisible"
      title="镜像详情"
      width="600px"
      class="glass-dialog"
    >
      <div class="details-content">
        <div class="detail-section">
          <h4><i class="fa fa-layer-group"></i> 基本信息</h4>
          <div class="detail-grid">
            <div class="detail-item">
              <label>镜像名称:</label>
              <span>{{ currentImageDetails.name || '-' }}</span>
            </div>
            <div class="detail-item">
              <label>项目:</label>
              <span>{{ currentImageDetails.project_name || selectedProject }}</span>
            </div>
            <div class="detail-item">
              <label>标签:</label>
              <span>{{ currentImageDetails.tag || '-' }}</span>
            </div>
            <div class="detail-item">
              <label>摘要:</label>
              <span class="digest-text">{{ currentImageDetails.digest || '-' }}</span>
            </div>
          </div>
        </div>

        <div class="detail-section">
          <h4><i class="fa fa-chart-bar"></i> 统计信息</h4>
          <div class="detail-grid">
            <div class="detail-item">
              <label>制品数量:</label>
              <span>{{ currentImageDetails.artifact_count || 0 }}</span>
            </div>
            <div class="detail-item">
              <label>拉取次数:</label>
              <span>{{ currentImageDetails.pull_count || 0 }}</span>
            </div>
            <div class="detail-item">
              <label>镜像大小:</label>
              <span>{{ currentImageDetails.size || '-' }}</span>
            </div>
            <div class="detail-item">
              <label>漏洞数量:</label>
              <span class="vulnerability-count">{{ currentImageDetails.vulnerability_count || 0 }}</span>
            </div>
          </div>
        </div>

        <div class="detail-section">
          <h4><i class="fa fa-clock"></i> 时间信息</h4>
          <div class="detail-grid">
            <div class="detail-item">
              <label>创建时间:</label>
              <span>{{ formatTime(currentImageDetails.creation_time) }}</span>
            </div>
            <div class="detail-item">
              <label>推送时间:</label>
              <span>{{ formatTime(currentImageDetails.push_time) }}</span>
            </div>
            <div class="detail-item">
              <label>更新时间:</label>
              <span>{{ formatTime(currentImageDetails.update_time) }}</span>
            </div>
          </div>
        </div>

        <div class="detail-section" v-if="currentImageDetails.description">
          <h4><i class="fa fa-file-text"></i> 描述信息</h4>
          <div class="description-text">
            {{ currentImageDetails.description }}
          </div>
        </div>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="detailsDialogVisible = false" class="glass-button">
            <i class="fa fa-times"></i>
            关闭
          </el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 清理镜像对话框 -->
    <el-dialog
      v-model="cleanupDialogVisible"
      title="清理Harbor镜像"
      width="500px"
      class="glass-dialog"
    >
      <div class="cleanup-dialog-content">
        <div class="warning-section">
          <i class="fa fa-exclamation-triangle warning-icon"></i>
          <h4>确认清理操作</h4>
          <p>此操作将清理以下类型的镜像：</p>
          <ul>
            <li>无标签的镜像（dangling images）</li>
            <li>超过保留策略的旧版本镜像</li>
            <li>未被引用的镜像层</li>
          </ul>
          <p class="warning-text">
            <strong>注意：此操作不可恢复，请确认后再执行！</strong>
          </p>
        </div>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="cleanupDialogVisible = false" class="glass-button">
            取消
          </el-button>
          <el-button @click="confirmCleanupImages" type="danger" class="glass-button delete-button">
            <i class="fa fa-trash"></i>
            确认清理
          </el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 漏洞扫描结果对话框 -->
    <el-dialog
      v-model="scanDialogVisible"
      title="漏洞扫描结果"
      width="80%"
      class="glass-dialog"
      :close-on-click-modal="false"
    >
      <div class="scan-content">
        <!-- 扫描状态 -->
        <div class="scan-header">
          <div class="scan-info">
            <h3>{{ currentScanImage.name }}:{{ currentScanImage.tag }}</h3>
            <div class="scan-status">
              <el-tag v-if="scanLoading" type="info">
                <i class="fa fa-spinner fa-spin"></i>
                扫描中...
              </el-tag>
              <el-tag v-else-if="scanResult.status" :type="getScanStatusType(scanResult.status)">
                {{ getScanStatusText(scanResult.status) }}
              </el-tag>
            </div>
          </div>
        </div>

        <!-- 漏洞统计 -->
        <div v-if="!scanLoading && scanResult.summary" class="vulnerability-summary">
          <div class="summary-title">
            <i class="fa fa-chart-pie"></i>
            漏洞统计
          </div>
          <div class="summary-grid">
            <div class="vuln-item critical">
              <div class="vuln-count">{{ scanResult.summary.critical || 0 }}</div>
              <div class="vuln-label">严重</div>
            </div>
            <div class="vuln-item high">
              <div class="vuln-count">{{ scanResult.summary.high || 0 }}</div>
              <div class="vuln-label">高危</div>
            </div>
            <div class="vuln-item medium">
              <div class="vuln-count">{{ scanResult.summary.medium || 0 }}</div>
              <div class="vuln-label">中危</div>
            </div>
            <div class="vuln-item low">
              <div class="vuln-count">{{ scanResult.summary.low || 0 }}</div>
              <div class="vuln-label">低危</div>
            </div>
            <div class="vuln-item unknown">
              <div class="vuln-count">{{ scanResult.summary.unknown || 0 }}</div>
              <div class="vuln-label">未知</div>
            </div>
          </div>
        </div>

        <!-- 漏洞详情表格 -->
        <div v-if="!scanLoading && vulnerabilities.length > 0" class="vulnerability-details">
          <div class="details-title">
            <i class="fa fa-list"></i>
            漏洞详情
          </div>
          <el-table :data="vulnerabilities" class="glass-table" max-height="400">
            <el-table-column prop="id" label="CVE编号" width="150" show-overflow-tooltip />
            <el-table-column prop="severity" label="严重程度" width="100">
              <template #default="scope">
                <el-tag :type="getVulnSeverityType(scope.row.severity)" size="small">
                  {{ scope.row.severity }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="package" label="受影响包" width="200" show-overflow-tooltip />
            <el-table-column prop="version" label="版本" width="120" show-overflow-tooltip />
            <el-table-column prop="fixed_version" label="修复版本" width="120" show-overflow-tooltip />
            <el-table-column prop="description" label="描述" show-overflow-tooltip />
          </el-table>
        </div>

        <!-- 空状态 -->
        <div v-if="!scanLoading && !scanResult.summary && vulnerabilities.length === 0" class="empty-scan">
          <div class="empty-content">
            <i class="fa fa-shield-alt empty-icon"></i>
            <p>暂无扫描结果</p>
            <p class="empty-tip">请先启动漏洞扫描</p>
          </div>
        </div>

        <!-- 加载状态 -->
        <div v-if="scanLoading" class="scan-loading">
          <div class="loading-content">
            <i class="fa fa-spinner fa-spin loading-icon"></i>
            <p>正在扫描镜像漏洞...</p>
            <p class="loading-tip">这可能需要几分钟时间</p>
          </div>
        </div>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="scanDialogVisible = false" class="glass-button">
            关闭
          </el-button>
          <el-button
            @click="refreshScanResult"
            :loading="scanLoading"
            class="glass-button primary-button"
          >
            <i class="fa fa-refresh"></i>
            刷新结果
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { dockerRegistryAPI } from '@/api/docker'
import { ElMessage, ElMessageBox } from 'element-plus'
import { onMounted, reactive, ref, watch } from 'vue'
import { useRoute } from 'vue-router'

// 路由
const route = useRoute()

// 响应式数据
const loading = ref(false)
const selectedRegistry = ref('')
const selectedProject = ref('')
const harborRegistries = ref([])
const projects = ref([])
const images = ref([])

// 对话框状态
const pullDialogVisible = ref(false)
const cleanupDialogVisible = ref(false)
const detailsDialogVisible = ref(false)
const selectedImage = ref('')
const currentImageDetails = ref({})

// 漏洞扫描相关
const scanDialogVisible = ref(false)
const scanLoading = ref(false)
const currentScanImage = ref<any>({})
const scanResult = ref<any>({})
const vulnerabilities = ref<any[]>([])

// 统计数据
const statistics = reactive({
  total_images: 0,
  total_size: '0 MB',
  total_repositories: 0
})

// 页面加载
onMounted(() => {
  loadData()

  // 处理URL参数
  const registryId = route.query.registry_id
  const projectName = route.query.project_name

  if (registryId) {
    selectedRegistry.value = registryId as string
    if (projectName) {
      selectedProject.value = projectName as string
      ElMessage.success(`已自动选择仓库和项目: ${projectName}`)
    }
  }
})

// 加载数据
const loadData = async () => {
  loading.value = true
  try {
    await loadHarborRegistries()
    // 如果有选中的仓库和项目，自动加载镜像
    if (selectedRegistry.value && selectedProject.value) {
      await loadImages()
    }
  } catch (error) {
    console.error('加载数据失败:', error)
    ElMessage.error('加载数据失败')
  } finally {
    loading.value = false
  }
}

// 加载Harbor仓库列表
const loadHarborRegistries = async () => {
  try {
    console.log('🔄 开始加载Harbor仓库列表...')
    const response = await dockerRegistryAPI.getRegistries()
    console.log('📦 API响应:', response)
    const allRegistries = response.data.results || response.data || []
    harborRegistries.value = allRegistries.filter((registry: any) =>
      registry.registry_type === 'harbor' && registry.is_active
    )
    console.log('✅ Harbor仓库列表加载完成:', harborRegistries.value)

    // 如果有仓库且没有选中的仓库，默认选择第一个
    if (harborRegistries.value.length > 0 && !selectedRegistry.value) {
      selectedRegistry.value = harborRegistries.value[0].id
      await loadProjects()
    }
  } catch (error) {
    console.error('❌ 加载Harbor仓库失败:', error)
    ElMessage.error('加载Harbor仓库失败')
  }
}

// 加载项目列表
const loadProjects = async () => {
  if (!selectedRegistry.value) {
    projects.value = []
    return
  }

  try {
    console.log('🔄 开始加载Harbor项目列表...', selectedRegistry.value)
    const response = await dockerRegistryAPI.getHarborProjects(selectedRegistry.value, {
      page: 1,
      page_size: 100
    })
    console.log('📦 Harbor项目API响应:', response)

    if (response.data.success) {
      projects.value = response.data.data || []
      console.log('✅ Harbor项目列表加载完成:', projects.value)

      // 如果有项目且没有选中的项目，默认选择第一个
      if (projects.value.length > 0 && !selectedProject.value) {
        selectedProject.value = projects.value[0].name
        await loadImages()
      }
    } else {
      ElMessage.error(response.data.message || '加载项目列表失败')
      projects.value = []
    }
  } catch (error) {
    console.error('❌ 加载Harbor项目列表失败:', error)
    ElMessage.error('加载项目列表失败')
    projects.value = []
  }
}

// 加载镜像列表
const loadImages = async () => {
  if (!selectedRegistry.value || !selectedProject.value) {
    images.value = []
    return
  }

  loading.value = true
  try {
    console.log('🔄 开始加载Harbor镜像列表...', selectedRegistry.value, selectedProject.value)
    // 这里需要先获取仓库列表，然后获取镜像
    const repoResponse = await dockerRegistryAPI.getHarborRepositories(selectedRegistry.value, selectedProject.value, {
      page: 1,
      page_size: 100
    })

    if (repoResponse.data.success) {
      const repositories = repoResponse.data.data || []
      console.log('✅ Harbor仓库列表加载完成:', repositories)

      // 为每个仓库获取镜像
      const allImages = []
      console.log('🔍 开始处理仓库列表:', repositories)

      for (const repo of repositories) {
        try {
          // 处理仓库名称 - 去掉项目名前缀
          let repositoryName = repo.name
          if (repositoryName.startsWith(`${selectedProject.value}/`)) {
            repositoryName = repositoryName.substring(`${selectedProject.value}/`.length)
          }

          console.log(`🔄 获取仓库 ${repo.name} (处理后: ${repositoryName}) 的镜像...`)

          const artifactResponse = await dockerRegistryAPI.getHarborArtifacts(
            selectedRegistry.value,
            selectedProject.value,
            repositoryName,
            { page: 1, page_size: 50 }
          )

          if (artifactResponse.data.success) {
            const artifacts = artifactResponse.data.data || []
            console.log(`✅ 仓库 ${repo.name} 获取到 ${artifacts.length} 个artifacts`)

            artifacts.forEach(artifact => {
              if (artifact.tags && artifact.tags.length > 0) {
                artifact.tags.forEach(tag => {
                  allImages.push({
                    name: repo.name, // 完整仓库名称
                    tag: tag.name,   // tag名称
                    digest: artifact.digest,
                    size: formatSize(artifact.size || 0),
                    push_time: formatTime(tag.push_time)
                  })
                })
              } else {
                // 处理没有tag的artifact（使用digest）
                allImages.push({
                  name: repo.name,
                  tag: 'none',
                  digest: artifact.digest,
                  size: formatSize(artifact.size || 0),
                  push_time: formatTime(artifact.push_time)
                })
              }
            })
          } else {
            console.warn(`⚠️ 获取仓库 ${repo.name} 的镜像失败:`, artifactResponse.data.message)
            // 即使获取失败，也要记录这个仓库存在
            allImages.push({
              name: repo.name,
              tag: 'unknown',
              digest: 'unknown',
              size: '0 B',
              push_time: '未知',
              error: true
            })
          }
        } catch (error) {
          console.error(`❌ 获取仓库 ${repo.name} 的镜像失败:`, error)
          // 即使获取失败，也要记录这个仓库存在
          allImages.push({
            name: repo.name,
            tag: 'error',
            digest: 'error',
            size: '0 B',
            push_time: '错误',
            error: true
          })
        }
      }

      images.value = allImages
      console.log('✅ Harbor镜像列表加载完成:', images.value)

      // 更新统计数据
      statistics.total_images = images.value.length
      statistics.total_repositories = repositories.length
      statistics.total_size = formatSize(repositories.reduce((sum, repo) => sum + (repo.size || 0), 0))
    } else {
      ElMessage.error(repoResponse.data.message || '加载仓库列表失败')
      images.value = []
    }
  } catch (error) {
    console.error('❌ 加载Harbor镜像列表失败:', error)
    ElMessage.error('加载镜像列表失败')
    images.value = []
  } finally {
    loading.value = false
  }
}

// 刷新镜像列表
const refreshImages = () => {
  loadImages()
  ElMessage.success('镜像列表已刷新')
}

// 拉取镜像（从Harbor拉取到本地Docker）
const pullImage = () => {
  if (!selectedRegistry.value || !selectedProject.value) {
    ElMessage.warning('请先选择Harbor仓库和项目')
    return
  }

  if (images.value.length === 0) {
    ElMessage.warning('当前项目没有可拉取的镜像')
    return
  }

  // 显示镜像选择对话框
  pullDialogVisible.value = true
}

// 清理镜像（清理Harbor中的无用镜像）
const cleanupImages = () => {
  if (!selectedRegistry.value || !selectedProject.value) {
    ElMessage.warning('请先选择Harbor仓库和项目')
    return
  }

  // 显示清理镜像对话框
  cleanupDialogVisible.value = true
}

// 查看详情
const viewDetails = (image: any) => {
  currentImageDetails.value = {
    ...image,
    project_name: image.project_name || selectedProject.value
  }
  detailsDialogVisible.value = true
}

// 启动漏洞扫描
const startVulnerabilityScan = async (image: any) => {
  try {
    console.log('🔍 开始漏洞扫描:', {
      registry: selectedRegistry.value,
      project: selectedProject.value,
      imageName: image.name,
      tag: image.tag,
      fullImage: image
    })

    currentScanImage.value = image
    scanDialogVisible.value = true
    scanLoading.value = true
    scanResult.value = {}
    vulnerabilities.value = []

    // 触发扫描
    const scanResponse = await dockerRegistryAPI.scanHarborArtifact(
      selectedRegistry.value,
      selectedProject.value,
      image.name,
      image.tag || 'latest'
    )

    if (scanResponse.data.success) {
      ElMessage.success('漏洞扫描已启动，正在获取结果...')

      // 等待一段时间后获取结果
      setTimeout(async () => {
        await getScanResult(image)
      }, 3000)
    } else {
      ElMessage.error(scanResponse.data.message || '启动扫描失败')
      scanLoading.value = false
    }
  } catch (error) {
    console.error('启动漏洞扫描失败:', error)

    // 显示Harbor扫描器配置提示
    ElMessageBox.alert(
      `Harbor扫描器未配置，请按以下步骤配置：

1. 登录Harbor Web界面 (http://10.0.0.52)
2. 进入 Administration → Interrogation Services
3. 点击 "NEW SCANNER" 添加Trivy扫描器
4. 配置信息：
   • Name: Trivy
   • Endpoint URL: http://trivy-adapter:8080
   • 其他选项保持默认
5. 保存并设为默认扫描器

配置完成后即可使用漏洞扫描功能。`,
      'Harbor扫描器配置',
      {
        confirmButtonText: '我知道了',
        type: 'warning',
        customClass: 'glass-dialog'
      }
    )

    scanLoading.value = false
  }
}

// 获取扫描结果
const getScanResult = async (image: any) => {
  try {
    const response = await dockerRegistryAPI.getHarborVulnerabilities(
      selectedRegistry.value,
      selectedProject.value,
      image.name,
      image.tag || 'latest'
    )

    if (response.data.success) {
      const data = response.data.data

      // 解析扫描概览
      const scanOverview = data.scan_overview || {}
      const scannerReports = Object.values(scanOverview)[0] as any || {}

      scanResult.value = {
        status: scannerReports.scan_status,
        summary: scannerReports.summary?.summary || {},
        start_time: scannerReports.start_time,
        end_time: scannerReports.end_time
      }

      // 解析漏洞详情
      const vulnData = data.vulnerabilities || {}
      const vulnList = Object.values(vulnData)[0] as any || []

      vulnerabilities.value = (vulnList.vulnerabilities || []).map((vuln: any) => ({
        id: vuln.id,
        severity: vuln.severity,
        package: vuln.package,
        version: vuln.version,
        fixed_version: vuln.fixed_version,
        description: vuln.description,
        links: vuln.links
      }))

      scanLoading.value = false
    } else {
      ElMessage.error(response.data.message || '获取扫描结果失败')
      scanLoading.value = false
    }
  } catch (error) {
    console.error('获取扫描结果失败:', error)
    ElMessage.error('获取扫描结果失败')
    scanLoading.value = false
  }
}

// 刷新扫描结果
const refreshScanResult = async () => {
  if (currentScanImage.value.name) {
    scanLoading.value = true
    await getScanResult(currentScanImage.value)
  }
}

// 获取扫描状态类型
const getScanStatusType = (status: string) => {
  switch (status) {
    case 'Success': return 'success'
    case 'Running': return 'info'
    case 'Error': return 'danger'
    case 'Stopped': return 'warning'
    default: return 'info'
  }
}

// 获取扫描状态文本
const getScanStatusText = (status: string) => {
  switch (status) {
    case 'Success': return '扫描完成'
    case 'Running': return '扫描中'
    case 'Error': return '扫描失败'
    case 'Stopped': return '扫描停止'
    default: return '未知状态'
  }
}

// 获取漏洞严重程度类型
const getVulnSeverityType = (severity: string) => {
  switch (severity?.toLowerCase()) {
    case 'critical': return 'danger'
    case 'high': return 'danger'
    case 'medium': return 'warning'
    case 'low': return 'info'
    default: return ''
  }
}

// 查看漏洞扫描
const viewVulnerabilities = (image: any) => {
  ElMessageBox.alert(
    `镜像: ${image.full_name}\n\n` +
    `漏洞扫描结果：\n` +
    `• 高危漏洞: 0\n` +
    `• 中危漏洞: 2\n` +
    `• 低危漏洞: 5\n` +
    `• 扫描时间: ${formatTime(new Date())}\n\n` +
    `建议及时修复中高危漏洞`,
    '漏洞扫描报告',
    {
      confirmButtonText: '确定',
      type: 'warning'
    }
  )
}

// 获取仓库URL
const getRegistryUrl = () => {
  const registry = harborRegistries.value.find(r => r.id === selectedRegistry.value)
  return registry ? registry.url.replace(/^https?:\/\//, '') : 'harbor.example.com'
}

// 确认拉取镜像
const confirmPullImage = () => {
  if (!selectedImage.value) {
    ElMessage.warning('请选择要拉取的镜像')
    return
  }

  const pullCommand = `docker pull ${getRegistryUrl()}/${selectedImage.value}`
  navigator.clipboard.writeText(pullCommand)
  ElMessage.success('拉取命令已复制到剪贴板，请在Docker环境中执行')
  pullDialogVisible.value = false
}

// 确认清理镜像
const confirmCleanupImages = () => {
  ElMessage.success('镜像清理任务已启动，将清理无标签和未使用的镜像')
  cleanupDialogVisible.value = false
  // 这里可以调用实际的清理API
}

// 删除镜像
const deleteImage = async (image: any) => {
  try {
    await ElMessageBox.confirm(
      `确定要删除镜像 "${image.name}:${image.tag}" 吗？此操作不可恢复！`,
      '删除确认',
      {
        confirmButtonText: '确定删除',
        cancelButtonText: '取消',
        type: 'warning',
      }
    )

    // 调用Harbor API删除镜像
    const response = await dockerRegistryAPI.deleteHarborArtifact(
      selectedRegistry.value,
      selectedProject.value,
      image.name,
      image.tag || 'latest'
    )

    if (response.data.success) {
      ElMessage.success('镜像删除成功')
      // 重新加载镜像列表
      await loadImages()
    } else {
      ElMessage.error(response.data.message || '删除镜像失败')
    }
  } catch (error) {
    if (error !== 'cancel') {
      console.error('删除镜像失败:', error)
      ElMessage.error('删除镜像失败')
    }
  }
}

// 格式化大小
const formatSize = (bytes: number) => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 格式化时间
const formatTime = (time: string) => {
  if (!time) return '-'
  return new Date(time).toLocaleString('zh-CN')
}

// 监听仓库选择变化
watch(selectedRegistry, async (newVal) => {
  if (newVal) {
    await loadProjects()
  }
})

// 监听项目选择变化
watch(selectedProject, async (newVal) => {
  if (newVal) {
    await loadImages()
  }
})
</script>

<style scoped>
/* 使用与Docker镜像管理页面完全相同的样式 */
.ansible-audit-container {
  min-height: 100vh;
  background: linear-gradient(
    135deg,
    rgba(0, 0, 0, 0.9) 0%,
    rgba(20, 20, 40, 0.95) 50%,
    rgba(0, 0, 0, 0.9) 100%
  );
  overflow-x: hidden;
}

.starry-background {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}

.stars, .stars2, .stars3 {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: transparent;
}

.stars {
  background-image:
    radial-gradient(2px 2px at 20px 30px, #eee, transparent),
    radial-gradient(2px 2px at 40px 70px, rgba(255,255,255,0.8), transparent),
    radial-gradient(1px 1px at 90px 40px, #fff, transparent),
    radial-gradient(1px 1px at 130px 80px, rgba(255,255,255,0.6), transparent),
    radial-gradient(2px 2px at 160px 30px, #ddd, transparent);
  background-repeat: repeat;
  background-size: 200px 100px;
  animation: zoom 20s infinite linear;
}

.stars2 {
  background-image:
    radial-gradient(1px 1px at 40px 50px, #fff, transparent),
    radial-gradient(1px 1px at 90px 80px, rgba(255,255,255,0.8), transparent),
    radial-gradient(1px 1px at 130px 20px, #eee, transparent),
    radial-gradient(2px 2px at 160px 60px, rgba(255,255,255,0.6), transparent);
  background-repeat: repeat;
  background-size: 200px 120px;
  animation: zoom 40s infinite linear;
}

.stars3 {
  background-image:
    radial-gradient(1px 1px at 60px 90px, #fff, transparent),
    radial-gradient(1px 1px at 100px 40px, rgba(255,255,255,0.7), transparent),
    radial-gradient(2px 2px at 140px 70px, #eee, transparent);
  background-repeat: repeat;
  background-size: 250px 150px;
  animation: zoom 60s infinite linear;
}

@keyframes zoom {
  from { transform: scale(1); }
  to { transform: scale(1.5); }
}

.audit-content {
  position: relative;
  z-index: 1;
  padding: 24px;
}

.glass-effect {
  background: rgba(164, 244, 186, 0.1);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 12px;
  backdrop-filter: blur(20px);
  box-shadow:
    0 8px 32px rgba(0, 0, 0, 0.3),
    inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

.page-header {
  margin-bottom: 24px;
  padding: 24px;
}

.header-content {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 24px;
}

.title-section {
  flex: 1;
}

.page-title {
  font-size: 28px;
  font-weight: 700;
  color: #00eaff;
  margin: 0 0 8px 0;
  display: flex;
  align-items: center;
  gap: 12px;
}

.page-title i {
  color: #a4f4ba;
  font-size: 24px;
}

.page-subtitle {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.7);
  margin: 0;
  line-height: 1.5;
}

.stats-section {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

.stat-card {
  min-width: 120px;
  padding: 16px 20px;
  text-align: center;
  transition: all 0.3s ease;
}

.stat-card:hover {
  background: rgba(164, 244, 186, 0.15);
  border-color: rgba(164, 244, 186, 0.3);
  transform: translateY(-2px);
}

.stat-number {
  font-size: 24px;
  font-weight: 700;
  color: #00eaff;
  margin-bottom: 4px;
  line-height: 1;
}

.stat-label {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.8);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  line-height: 1;
}

/* 搜索过滤器 */
.search-filters {
  margin-bottom: 24px;
  padding: 20px;
}

.search-form {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
}

.form-left {
  display: flex;
  align-items: center;
  gap: 16px;
}

.form-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

.server-select {
  min-width: 200px;
}

.registry-option {
  display: flex;
  align-items: center;
  gap: 8px;
}

.registry-option i {
  color: #a4f4ba;
}

.registry-url {
  color: rgba(255, 255, 255, 0.6);
  font-size: 12px;
}

/* 审计表格区域 */
.audit-table-section {
  margin-bottom: 24px;
  overflow: hidden;
}

.section-title {
  font-size: 18px;
  font-weight: 600;
  color: #00eaff;
  margin-bottom: 20px;
  padding: 0 24px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.section-title i {
  color: #a4f4ba;
}

/* 审计表格样式 */
.audit-table {
  background: transparent !important;
}

.audit-table :deep(.el-table__header) {
  background: rgba(164, 244, 186, 0.05) !important;
}

.audit-table :deep(.el-table__header th) {
  background: transparent !important;
  border-bottom: 1px solid rgba(164, 244, 186, 0.2) !important;
  color: #00eaff !important;
  font-weight: 600 !important;
  padding: 16px 12px !important;
}

.audit-table :deep(.el-table__body tr) {
  background: transparent !important;
  transition: all 0.3s ease !important;
}

.audit-table :deep(.el-table__body tr:hover) {
  background: rgba(164, 244, 186, 0.05) !important;
}

.audit-table :deep(.el-table__body td) {
  border-bottom: 1px solid rgba(164, 244, 186, 0.1) !important;
  color: rgba(255, 255, 255, 0.9) !important;
  padding: 16px 12px !important;
}

.audit-row {
  transition: all 0.3s ease;
}

.audit-row:hover {
  background: rgba(164, 244, 186, 0.05) !important;
}

/* 配置名称样式 */
.config-name {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 500;
}

.config-name i {
  color: #a4f4ba;
  font-size: 14px;
}

/* 镜像ID样式 */
.image-id {
  font-family: 'Courier New', monospace;
  color: #a4f4ba;
  font-size: 12px;
}

/* 大小文本样式 */
.size-text {
  color: #00eaff;
  font-weight: 500;
}

/* 时间文本样式 */
.time-text {
  color: rgba(255, 255, 255, 0.8);
  font-size: 12px;
}

/* 操作按钮样式 */
.action-buttons {
  display: flex;
  gap: 6px;
  flex-wrap: nowrap;
  align-items: center;
  justify-content: flex-start;
}

.action-buttons .glass-button {
  min-width: 70px !important;
  max-width: 85px !important;
  white-space: nowrap !important;
  text-align: center !important;
  padding: 6px 10px !important;
  font-size: 12px !important;
}

/* 按钮样式 */
.glass-button {
  background: rgba(164, 244, 186, 0.15) !important;
  border: 1px solid rgba(164, 244, 186, 0.3) !important;
  color: rgba(255, 255, 255, 0.9) !important;
  transition: all 0.3s ease !important;
  backdrop-filter: blur(10px) !important;
  border-radius: 6px !important;
  padding: 6px 12px !important;
  font-size: 12px !important;
}

.glass-button:hover {
  background: rgba(164, 244, 186, 0.25) !important;
  border-color: rgba(164, 244, 186, 0.5) !important;
  transform: translateY(-1px) !important;
}

.glass-button i {
  margin-right: 4px;
}

.refresh-button {
  background: rgba(0, 234, 255, 0.2) !important;
  border-color: rgba(0, 234, 255, 0.4) !important;
  color: #00eaff !important;
}

.refresh-button:hover {
  background: rgba(0, 234, 255, 0.3) !important;
  border-color: rgba(0, 234, 255, 0.6) !important;
}

.add-button {
  background: rgba(46, 204, 113, 0.2) !important;
  border-color: rgba(46, 204, 113, 0.4) !important;
  color: #2ecc71 !important;
}

.add-button:hover {
  background: rgba(46, 204, 113, 0.3) !important;
  border-color: rgba(46, 204, 113, 0.6) !important;
}

.sync-button {
  background: rgba(155, 89, 182, 0.2) !important;
  border-color: rgba(155, 89, 182, 0.4) !important;
  color: #9b59b6 !important;
}

.sync-button:hover {
  background: rgba(155, 89, 182, 0.3) !important;
  border-color: rgba(155, 89, 182, 0.6) !important;
}

.delete-button {
  background: rgba(231, 76, 60, 0.2) !important;
  border-color: rgba(231, 76, 60, 0.4) !important;
  color: #e74c3c !important;
}

.delete-button:hover {
  background: rgba(231, 76, 60, 0.3) !important;
  border-color: rgba(231, 76, 60, 0.6) !important;
}

.info-button {
  background: rgba(52, 152, 219, 0.2) !important;
  border-color: rgba(52, 152, 219, 0.4) !important;
  color: #3498db !important;
}

.info-button:hover {
  background: rgba(52, 152, 219, 0.3) !important;
  border-color: rgba(52, 152, 219, 0.6) !important;
}

.warning-button {
  background: rgba(241, 196, 15, 0.2) !important;
  border-color: rgba(241, 196, 15, 0.4) !important;
  color: #f1c40f !important;
}

.warning-button:hover {
  background: rgba(241, 196, 15, 0.3) !important;
  border-color: rgba(241, 196, 15, 0.6) !important;
}

/* 空状态 */
.empty-state {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 400px;
  padding: 40px;
}

.empty-content {
  text-align: center;
}

.empty-icon {
  font-size: 64px;
  color: rgba(255, 255, 255, 0.3);
  margin-bottom: 16px;
}

.empty-content h3 {
  color: rgba(255, 255, 255, 0.8);
  margin-bottom: 8px;
  font-size: 18px;
}

.empty-content p {
  color: rgba(255, 255, 255, 0.6);
  margin: 0;
  font-size: 14px;
}

/* 对话框样式 */
.pull-dialog-content,
.push-dialog-content,
.cleanup-dialog-content {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.dialog-section {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.dialog-section h4 {
  color: #00eaff;
  margin: 0;
  font-size: 14px;
  font-weight: 600;
}

.full-width {
  width: 100%;
}

.image-option {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.image-name {
  color: #ffffff;
}

.image-size {
  color: rgba(255, 255, 255, 0.6);
  font-size: 12px;
}

.command-box {
  background: rgba(0, 0, 0, 0.3);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 6px;
  padding: 12px;
  font-family: 'Courier New', monospace;
}

.command-line {
  margin-bottom: 8px;
}

.command-line:last-child {
  margin-bottom: 0;
}

.command-box code {
  color: #a4f4ba;
  font-size: 12px;
  word-break: break-all;
}

.command-tip {
  display: flex;
  align-items: center;
  gap: 8px;
  color: rgba(255, 255, 255, 0.7);
  font-size: 12px;
  margin: 0;
}

.command-tip i {
  color: #00eaff;
}

.warning-section {
  text-align: center;
}

.warning-icon {
  font-size: 48px;
  color: #ff6b6b;
  margin-bottom: 16px;
}

.warning-section h4 {
  color: #ff6b6b;
  margin-bottom: 16px;
}

.warning-section ul {
  text-align: left;
  color: rgba(255, 255, 255, 0.8);
  margin: 16px 0;
}

.warning-section li {
  margin-bottom: 8px;
}

.warning-text {
  color: #ff6b6b;
  font-size: 14px;
  margin-top: 16px;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

.primary-button {
  background: rgba(0, 234, 255, 0.2) !important;
  border-color: rgba(0, 234, 255, 0.4) !important;
  color: #00eaff !important;
}

.primary-button:hover {
  background: rgba(0, 234, 255, 0.3) !important;
  border-color: rgba(0, 234, 255, 0.6) !important;
}

/* 详情对话框样式 */
.details-content {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.detail-section {
  background: rgba(164, 244, 186, 0.05);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 8px;
  padding: 16px;
}

.detail-section h4 {
  color: #a4f4ba;
  margin: 0 0 12px 0;
  font-size: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.detail-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.detail-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.detail-item label {
  color: rgba(255, 255, 255, 0.7);
  font-size: 12px;
  font-weight: 500;
}

.detail-item span {
  color: rgba(255, 255, 255, 0.9);
  font-size: 14px;
  word-break: break-all;
}

.digest-text {
  font-family: 'Courier New', monospace;
  font-size: 12px !important;
  color: #00eaff !important;
}

.vulnerability-count {
  color: #f39c12 !important;
  font-weight: 500;
}

.description-text {
  background: rgba(0, 0, 0, 0.2);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 6px;
  padding: 12px;
  color: rgba(255, 255, 255, 0.8);
  font-size: 14px;
  line-height: 1.5;
}

/* 漏洞扫描对话框样式 */
.scan-content {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.scan-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px;
  background: rgba(164, 244, 186, 0.05);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 8px;
}

.scan-info h3 {
  color: #a4f4ba;
  margin: 0 0 8px 0;
  font-size: 18px;
}

.scan-status {
  display: flex;
  align-items: center;
  gap: 8px;
}

.vulnerability-summary {
  background: rgba(164, 244, 186, 0.05);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 8px;
  padding: 20px;
}

.summary-title {
  color: #a4f4ba;
  font-size: 16px;
  font-weight: 500;
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.summary-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 16px;
}

.vuln-item {
  text-align: center;
  padding: 16px;
  border-radius: 8px;
  background: rgba(0, 0, 0, 0.2);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.vuln-item.critical {
  border-color: rgba(245, 101, 101, 0.5);
  background: rgba(245, 101, 101, 0.1);
}

.vuln-item.high {
  border-color: rgba(245, 166, 35, 0.5);
  background: rgba(245, 166, 35, 0.1);
}

.vuln-item.medium {
  border-color: rgba(250, 173, 20, 0.5);
  background: rgba(250, 173, 20, 0.1);
}

.vuln-item.low {
  border-color: rgba(103, 194, 58, 0.5);
  background: rgba(103, 194, 58, 0.1);
}

.vuln-item.unknown {
  border-color: rgba(144, 147, 153, 0.5);
  background: rgba(144, 147, 153, 0.1);
}

.vuln-count {
  font-size: 24px;
  font-weight: bold;
  color: rgba(255, 255, 255, 0.9);
  margin-bottom: 4px;
}

.vuln-label {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.7);
}

.vulnerability-details {
  background: rgba(164, 244, 186, 0.05);
  border: 1px solid rgba(164, 244, 186, 0.2);
  border-radius: 8px;
  padding: 20px;
}

.details-title {
  color: #a4f4ba;
  font-size: 16px;
  font-weight: 500;
  margin-bottom: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.empty-scan {
  text-align: center;
  padding: 60px 20px;
}

.empty-scan .empty-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.empty-scan .empty-icon {
  font-size: 48px;
  color: rgba(255, 255, 255, 0.3);
}

.empty-scan p {
  color: rgba(255, 255, 255, 0.6);
  margin: 0;
}

.empty-scan .empty-tip {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.4);
}

.scan-loading {
  text-align: center;
  padding: 60px 20px;
}

.loading-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.loading-icon {
  font-size: 32px;
  color: #a4f4ba;
}

.scan-loading p {
  color: rgba(255, 255, 255, 0.8);
  margin: 0;
}

.loading-tip {
  font-size: 12px;
  color: rgba(255, 255, 255, 0.5);
}
</style>
